class CommandParser (object):
    def __init__(self):
        self.commands = {"PING": PingCommand, "PONG": PongCommand, "MSG": MsgCommand, "NAME": NameCommand, "PASS": PassCommand, "SETPASS": SetpassCommand, "JOIN": JoinCommand, "LEAVE": LeaveCommand, "WHO": WhoCommand}
        self.responses = {"NAME": NameResponse, "WHO": WhoResponse, "JOIN": JoinResponse}

    def parse_string(self, string):
        command = string.split(" ")
        if command[0] == "CMD":
            if command[1] in self.commands:
                command_class = self.commands[command[1]]
                command_arguments = " ".join(command[2:])
                return command_class.parse_from_string(command_arguments)
            else:
                error_string = "%s is not a valid command" % command[0]
                print error_string
                raise ValueError(error_string)
        elif command[0] == "RESP":
            if command[1] in self.responses:
                response_class = self.responses[command[1]]
                response_arguments = " ".join(command[2:])
                return response_class.parse_from_string(response_arguments)
        else:
            raise ValueError("Invalid command prefix")


class Command (object):
    format = None

    @classmethod
    def parse_from_string(cls, arguments):
        raise NotImplementedError("Command not implemented by subclass")


class PingCommand (Command):
    format = "CMD PING %s"

    def __init__(self, timestamp):

        self.timestamp = timestamp

    def __str__(self):
        return self.format % self.timestamp

    @classmethod
    def parse_from_string(cls, arguments):
        arguments_split = arguments.split(" ")
        if len(arguments_split) == 1:
            return cls(arguments_split[0])
        else:
            raise ValueError


class PongCommand (Command):
    format = "CMD PONG %s"

    def __init__(self, timestamp):
        self.timestamp = timestamp

    def __str__(self):
        return self.format % self.timestamp

    @classmethod
    def parse_from_string(cls, arguments):
        arguments_split = arguments.split(" ")
        if len(arguments_split) == 1:
            return cls(arguments_split[0])
        else:
            raise ValueError


class MsgCommand (Command):
    format = "CMD MSG %s %s"

    def __init__(self, target, message):
        self.target = target
        self.message = message

    def __str__(self):
        return self.format % (self.target, self.message)

    @classmethod
    def parse_from_string(cls, arguments):
        arguments_split = arguments.split(" ")
        if len(arguments_split) >= 2:
            target = arguments_split[0]
            message = " ".join(arguments_split[1:])
            return cls(target, message)
        else:
            raise ValueError


class NameCommand (Command):
    format = "CMD NAME %s"

    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.format % self.name

    @classmethod
    def parse_from_string(cls, arguments):
        arguments_split = arguments.split(" ")
        if len(arguments_split) == 1:
            return cls(arguments_split[0])
        else:
            raise ValueError


class PassCommand (Command):
    format = "CMD PASS %s"

    def __init__(self, password):
        self.password = password

    def __str__(self):
        return self.format % self.password


class SetpassCommand (Command):
    format = "CMD SETPASS %s"

    def __init__(self, password):
        self.password = password

    def __str__(self):
        return self.format % self.password


class JoinCommand (Command):
    format = "CMD JOIN %s"

    def __init__(self, channel):
        self.channel = channel

    def __str__(self):
        return self.format % self.channel

    @classmethod
    def parse_from_string(cls, arguments):
        arguments_split = arguments.split(" ")
        if len(arguments_split) == 1:
            return cls(arguments_split[0])
        else:
            raise ValueError


class LeaveCommand (Command):
    format = "CMD LEAVE %s"

    def __init__(self, channel):
        self.channel = channel

    def __str__(self):
        return self.format % self.channel


class WhoCommand (Command):
    format = "CMD WHO"

    def __str__(self):
        return self.format

    @classmethod
    def parse_from_string(cls, arguments):
        return cls()


class Response (object):
    format = None

    @classmethod
    def parse_from_string(cls, arguments):
        raise NotImplementedError("Response not implemented by subclass")


class NameResponse (Response):
    format = "RESP NAME %s"

    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.format % self.name

    @classmethod
    def parse_from_string(cls, arguments):
        arguments_split = arguments.split(" ")
        if len(arguments_split) == 1:
            return cls(arguments_split[0])
        else:
            raise ValueError


class WhoResponse (Response):
    format = "RESP WHO %s"

    def __init__(self, connected_users):
        self.connected_users = connected_users

    def __str__(self):
        return self.format % self.connected_users

    @classmethod
    def parse_from_string(cls, arguments):
        arguments_split = arguments.split(" ")
        if len(arguments_split) >= 2:
            return cls(arguments)
        else:
            raise ValueError


class JoinResponse (Response):
    format = "RESP JOIN %s %s"

    def __init__(self, username, channel):
        self.username = username
        self.channel = channel

    def __str__(self):
        return self.format % (self.username, self.channel)

    @classmethod
    def parse_from_string(cls, arguments):
        arguments_split = arguments.split(" ")
        if len(arguments_split) == 2:
            return cls(arguments_split[0], arguments_split[1])
        else:
            raise ValueError